package com.zhouxiaoxuan13.consumer.monitor;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnStateTransitionEvent;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnSuccessEvent;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnErrorEvent;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnFailureRateExceededEvent;
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnCallNotPermittedEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 熔断器状态监控组件
 * 监控熔断器状态变化并在控制台输出详细信息
 */
@Slf4j
@Component
public class CircuitBreakerMonitor {

    @Autowired(required = false)
    private CircuitBreakerRegistry circuitBreakerRegistry;

    private final AtomicLong eventCounter = new AtomicLong(0);
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

    @PostConstruct
    public void init() {
        if (circuitBreakerRegistry != null) {
            log.info("🔧 初始化熔断器监控器...");
            setupCircuitBreakerEventListeners();
        } else {
            log.warn("⚠️ CircuitBreakerRegistry 未找到，熔断器监控功能不可用");
        }
    }

    /**
     * 设置熔断器事件监听器
     */
    private void setupCircuitBreakerEventListeners() {
        circuitBreakerRegistry.getAllCircuitBreakers().forEach(this::registerEventListeners);
        
        // 监听新注册的熔断器
        circuitBreakerRegistry.getEventPublisher().onEntryAdded(event -> {
            log.info("🆕 新熔断器注册: {}", event.getAddedEntry().getName());
            registerEventListeners(event.getAddedEntry());
        });
    }

    /**
     * 为熔断器注册事件监听器
     */
    private void registerEventListeners(CircuitBreaker circuitBreaker) {
        String circuitBreakerName = circuitBreaker.getName();
        log.info("📡 为熔断器 '{}' 注册事件监听器", circuitBreakerName);

        // 状态转换事件监听
        circuitBreaker.getEventPublisher().onStateTransition(this::handleStateTransition);
        
        // 成功调用事件监听
        circuitBreaker.getEventPublisher().onSuccess(this::handleSuccess);
        
        // 错误调用事件监听
        circuitBreaker.getEventPublisher().onError(this::handleError);
        
        // 失败率超过阈值事件监听
        circuitBreaker.getEventPublisher().onFailureRateExceeded(this::handleFailureRateExceeded);
        
        // 调用不被允许事件监听（熔断器打开状态）
        circuitBreaker.getEventPublisher().onCallNotPermitted(this::handleCallNotPermitted);
        
        // 通用事件监听
        circuitBreaker.getEventPublisher().onEvent(this::handleGenericEvent);
    }

    /**
     * 处理状态转换事件
     */
    private void handleStateTransition(CircuitBreakerOnStateTransitionEvent event) {
        long eventNum = eventCounter.incrementAndGet();
        String timestamp = LocalDateTime.now().format(formatter);
        
        log.info("🔄 ==================== 熔断器状态转换事件 #{} ====================", eventNum);
        log.info("🕒 时间: {}", timestamp);
        log.info("🏷️  熔断器名称: {}", event.getCircuitBreakerName());
        log.info("📊 状态转换: {} → {}", event.getStateTransition().getFromState(), event.getStateTransition().getToState());
        
        // 根据不同的状态转换输出特定信息
        switch (event.getStateTransition().getToState()) {
            case OPEN:
                log.error("🚨 熔断器已打开！服务调用将被熔断");
                printCircuitBreakerMetrics(event.getCircuitBreakerName());
                break;
            case HALF_OPEN:
                log.warn("🔍 熔断器进入半开状态，开始探测服务是否恢复");
                break;
            case CLOSED:
                log.info("✅ 熔断器已关闭，服务调用恢复正常");
                break;
            case FORCED_OPEN:
                log.error("🔒 熔断器被强制打开");
                break;
            case DISABLED:
                log.info("⏸️ 熔断器已禁用");
                break;
        }
        
        log.info("🔄 ================================================================");
    }

    /**
     * 处理成功调用事件
     */
    private void handleSuccess(CircuitBreakerOnSuccessEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("✅ 熔断器 '{}' 调用成功，耗时: {}ms", 
                event.getCircuitBreakerName(), 
                event.getElapsedDuration().toMillis());
        }
    }

    /**
     * 处理错误调用事件
     */
    private void handleError(CircuitBreakerOnErrorEvent event) {
        long eventNum = eventCounter.incrementAndGet();
        String timestamp = LocalDateTime.now().format(formatter);
        
        log.warn("❌ ==================== 熔断器错误事件 #{} ====================", eventNum);
        log.warn("🕒 时间: {}", timestamp);
        log.warn("🏷️  熔断器名称: {}", event.getCircuitBreakerName());
        log.warn("⏱️  调用耗时: {}ms", event.getElapsedDuration().toMillis());
        log.warn("🐛 异常类型: {}", event.getThrowable().getClass().getSimpleName());
        log.warn("📝 异常信息: {}", event.getThrowable().getMessage());
        log.warn("❌ ================================================================");
    }

    /**
     * 处理失败率超过阈值事件
     */
    private void handleFailureRateExceeded(CircuitBreakerOnFailureRateExceededEvent event) {
        long eventNum = eventCounter.incrementAndGet();
        String timestamp = LocalDateTime.now().format(formatter);

        log.error("📈 ==================== 失败率超过阈值事件 #{} ====================", eventNum);
        log.error("🕒 时间: {}", timestamp);
        log.error("🏷️  熔断器名称: {}", event.getCircuitBreakerName());
        log.error("📊 当前失败率: {:.2f}%", event.getFailureRate());
        log.error("🚨 熔断器即将打开！");
        log.error("📈 ================================================================");
    }

    /**
     * 处理调用不被允许事件（熔断器打开状态）
     */
    private void handleCallNotPermitted(CircuitBreakerOnCallNotPermittedEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("🚫 熔断器 '{}' 处于打开状态，调用被拒绝", event.getCircuitBreakerName());
        }
    }

    /**
     * 处理通用事件
     */
    private void handleGenericEvent(CircuitBreakerEvent event) {
        // 这里可以添加通用的事件处理逻辑
        // 目前只记录调试信息
        if (log.isTraceEnabled()) {
            log.trace("🔔 熔断器事件: {} - {}", event.getEventType(), event.getCircuitBreakerName());
        }
    }

    /**
     * 打印熔断器指标信息
     */
    private void printCircuitBreakerMetrics(String circuitBreakerName) {
        try {
            CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(circuitBreakerName);
            CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
            
            log.info("📊 ==================== 熔断器指标信息 ====================");
            log.info("🏷️  熔断器名称: {}", circuitBreakerName);
            log.info("📈 失败率: {:.2f}%", metrics.getFailureRate());
            log.info("🔢 调用总数: {}", metrics.getNumberOfBufferedCalls());
            log.info("❌ 失败调用数: {}", metrics.getNumberOfFailedCalls());
            log.info("✅ 成功调用数: {}", metrics.getNumberOfSuccessfulCalls());
            log.info("🐌 慢调用数: {}", metrics.getNumberOfSlowCalls());
            log.info("🚫 不允许调用数: {}", metrics.getNumberOfNotPermittedCalls());
            log.info("📊 ========================================================");
        } catch (Exception e) {
            log.error("获取熔断器指标信息失败: {}", e.getMessage());
        }
    }

    /**
     * 获取所有熔断器的状态信息
     */
    public void printAllCircuitBreakerStatus() {
        if (circuitBreakerRegistry == null) {
            log.warn("CircuitBreakerRegistry 不可用");
            return;
        }

        log.info("🔍 ==================== 所有熔断器状态 ====================");
        circuitBreakerRegistry.getAllCircuitBreakers().forEach(circuitBreaker -> {
            log.info("🏷️  熔断器: {} | 状态: {} | 失败率: {:.2f}%", 
                circuitBreaker.getName(),
                circuitBreaker.getState(),
                circuitBreaker.getMetrics().getFailureRate());
        });
        log.info("🔍 ========================================================");
    }
}
